using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Web;
using System.Web.Caching;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.IO;
using System.Drawing;

namespace InterpriseSuiteEcommerceCommon.Actions
{
    public class ViewCacheAction : IActionHandler
    {
        #region IActionHandler Members

        public string Name
        {
            get { return "viewCache"; }
        }

        public void Handle(System.Web.HttpContext context)
        {
            bool showSizes = CommonLogic.QueryStringBool("showsize");
            bool showValue = !CommonLogic.IsStringNullOrEmpty(CommonLogic.QueryStringCanBeDangerousContent("showValue"));

            StringBuilder html = new StringBuilder();

            html.Append("<html>\n");
            html.Append("<head>\n");
            html.Append("<title>Cache View</title>\n");
            html.Append("<style type=\"text/css\">\n");
            html.Append("body { \n");
            html.Append("font-family: Tahoma,Verdana,sans-serif; \n");
            html.Append("font-size: 12px !important; \n");
            html.Append("}");
            html.Append("body table{ \n");
            html.Append("font-family: Tahoma,Verdana,sans-serif; \n");
            html.Append("font-size: 12px !important; \n");
            html.Append("}");
            html.Append("body textarea{ \n");
            html.Append("font-family: Tahoma,Verdana,sans-serif; \n");
            html.Append("font-size: 12px !important; \n");
            html.Append("border: solid 1px black; \n");
            html.Append("}");
            html.Append("body table td{ \n");
            html.Append("border: solid 1px silver; \n");
            html.Append("}");
            html.Append("</style>\n");
            html.Append("</head>\n");
            html.Append("<body>\n");
            html.Append("<div>\n");
            if (showValue)
            {
                html.Append("<a href=\"action.axd?action=viewCache\">Back</a>");
            }
            else
            {
                html.Append("<a href=\"action.axd?action=viewCache&showsize=true\">Show Sizes</a>");
            }
            html.Append("<br />\n");

            html.Append("<br />\n");

            html.Append("<table style=\"width:350px;\" cellspacing=\"0\" cellpadding=\"0\" >\n");
            html.AppendFormat("<tr>\n");
            html.AppendFormat("<td style=\"width:50%;text-alight:left;background-color:#808080;\" >{0}</td>\n", "Cache Count");
            html.AppendFormat("<td style=\"width:50%;text-alight:left;\" >{0}</td>\n", HttpRuntime.Cache.Count);
            html.AppendFormat("</tr>\n");
            html.AppendFormat("<tr>\n");
            html.AppendFormat("<td style=\"width:50%;text-alight:left;background-color:#808080;\" >{0}</td>\n", "Effective Private Bytes Limit");
            html.AppendFormat("<td style=\"width:50%;text-alight:left;\" >{0}</td>\n", HttpRuntime.Cache.EffectivePrivateBytesLimit);
            html.AppendFormat("</tr>\n");
            html.AppendFormat("<tr>\n");
            html.AppendFormat("<td style=\"width:50%;text-alight:left;background-color:#808080;\" >{0}</td>\n", "Total Size");

            decimal totalSize = HttpRuntime.Cache.OfType<DictionaryEntry>()
                                                   .Sum(e =>
                                                   {

                                                       if (e.Value is string)
                                                       {
                                                           return (e.Value as string).Length;
                                                       }
                                                       else if (e.Value is StringBuilder)
                                                       {
                                                           return (e.Value as StringBuilder).Length;
                                                       }

                                                       return 0;
                                                   });

            html.AppendFormat("<td style=\"width:50%;text-alight:left;\" >{0}</td>\n", totalSize.ToString());
            html.AppendFormat("</tr>\n");
            html.Append("</table>\n");

            html.Append("<br />\n");
            if (showValue)
            {
                string key = CommonLogic.QueryStringCanBeDangerousContent("showvalue");
                object value = HttpRuntime.Cache[key];

                html.Append("<div>\n");
                if (value != null)
                {
                    html.AppendFormat("<span>Cache: <b>{0}</b></span>\n", key);
                    html.Append("<br />\n");
                    int size = 0;
                    if (value is string)
                    {
                        size = (value as string).Length;
                    }
                    else if (value is StringBuilder)
                    {
                        size = (value as StringBuilder).Length;
                    }
                    html.AppendFormat("<span>Size: <b>{0}</b></span>\n", size);
                    html.Append("<br />\n");
                    html.Append("<br />\n");
                    html.AppendFormat("<textarea width=\"100%\" rows=\"25\" cols=\"150\" >{0}</textarea>\n", value.ToString());
                }
                else
                {
                    html.AppendFormat("<span>Cache: <b>{0}</b> NOT EXISTING!!!</span>\n", key);
                }
                html.Append("</div>\n");
                html.Append("<br />\n");
            }
            else
            {
                TableBuilder output = new TableBuilder(showSizes);
                output.Width = Unit.Pixel(800);

                IEnumerator enumerator = HttpRuntime.Cache.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    DictionaryEntry cachedItem = (DictionaryEntry)enumerator.Current;
                    if (showSizes)
                    {
                        object value = cachedItem.Value;
                        int size = 0;
                        if (value is string)
                        {
                            size = (value as string).Length;
                        }
                        else if (value is StringBuilder)
                        {
                            size = (value as StringBuilder).Length;
                        }
                        output.AddRow(cachedItem.Key.ToString(), cachedItem.Value.GetType().ToString(), size);
                    }
                    else
                    {
                        output.AddRow(cachedItem.Key.ToString(), cachedItem.Value.GetType().ToString());
                    }
                }
                html.Append(output.HTML);
            }
            html.Append("\n</body>\n</html>\n");

            context.Response.Write(html.ToString());
        }

        #endregion
    }

    internal class TableBuilder
    {
        private Table _tblCache = new Table();
        private Color _rowColor = Color.White;
        private Color _alternatingColor = Color.FromArgb(245, 245, 245);
        private int _rows = 0;
        private bool _showSize = false;

        internal TableBuilder(bool showSize)
        {
            _tblCache.CellPadding = 0;
            _tblCache.CellSpacing = 0;
            _tblCache.BorderStyle = BorderStyle.Solid;
            _tblCache.BorderColor = Color.Black;
            _tblCache.BorderWidth = Unit.Pixel(1);

            _showSize = showSize;

            PrepareHeaders();
        }

        public Unit Width
        {
            get { return _tblCache.Width; }
            set { _tblCache.Width = value; }
        }

        private void PrepareHeaders()
        {
            Color backColor = Color.FromArgb(128, 128, 128);
            TableHeaderRow thrHeader = new TableHeaderRow();
            TableHeaderCell thcCacheName = new TableHeaderCell();
            if (_showSize)
            {
                thcCacheName.Width = Unit.Percentage(40);
            }
            else
            {
                thcCacheName.Width = Unit.Percentage(50);
            }
            thcCacheName.BackColor = backColor;
            thcCacheName.Controls.Add(new LiteralControl("Cache Name"));
            thrHeader.Cells.Add(thcCacheName);

            TableHeaderCell thcCacheValue = new TableHeaderCell();
            thcCacheValue.Width = Unit.Percentage(50);
            if (_showSize)
            {
                thcCacheValue.Width = Unit.Percentage(30);
            }
            else
            {
                thcCacheValue.Width = Unit.Percentage(50);
            }
            thcCacheValue.BackColor = backColor;
            thcCacheValue.Controls.Add(new LiteralControl("Type"));
            thrHeader.Cells.Add(thcCacheValue);

            if (_showSize)
            {
                TableHeaderCell thcCacheSize = new TableHeaderCell();
                thcCacheSize.Width = Unit.Percentage(30);
                thcCacheSize.BackColor = backColor;
                thcCacheSize.Controls.Add(new LiteralControl("Size"));
                thrHeader.Cells.Add(thcCacheSize);
            }

            _tblCache.Rows.Add(thrHeader);
        }

        public void AddRow(string name, string value)
        {
            AddRow(name, value, 0);
        }

        public void AddRow(string name, string value, int size)
        {
            _rows++;

            TableRow tr = new TableRow();

            Color backColor = _rowColor;
            if (_rows % 2 != 0)
            {
                backColor = _alternatingColor;
            }

            TableCell tc = new TableCell();
            if (_showSize)
            {
                tc.Width = Unit.Percentage(40);
            }
            else
            {
                tc.Width = Unit.Percentage(50);
            }
            tc.VerticalAlign = VerticalAlign.Top;
            tc.HorizontalAlign = HorizontalAlign.Left;
            tc.BackColor = backColor;
            HyperLink lnkName = new HyperLink();
            lnkName.NavigateUrl = "action.axd?action=viewCache&showValue=" + HttpUtility.UrlEncode(name);
            lnkName.Text = name;
            tc.Controls.Add(lnkName);
            tr.Cells.Add(tc);

            tc = new TableCell();
            if (_showSize)
            {
                tc.Width = Unit.Percentage(30);
            }
            else
            {
                tc.Width = Unit.Percentage(50);
            }
            tc.VerticalAlign = VerticalAlign.Top;
            tc.HorizontalAlign = HorizontalAlign.Center;
            tc.BackColor = backColor;
            tc.Controls.Add(new LiteralControl(value));
            tr.Cells.Add(tc);

            if (_showSize)
            {
                tc = new TableCell();
                tc.Width = Unit.Percentage(30);
                tc.VerticalAlign = VerticalAlign.Top;
                tc.HorizontalAlign = HorizontalAlign.Center;
                tc.BackColor = backColor;
                tc.Controls.Add(new LiteralControl(size.ToString()));
                tr.Cells.Add(tc);
            }

            _tblCache.Rows.Add(tr);
        }

        public string HTML
        {
            get
            {
                StringBuilder output = new StringBuilder();
                using (StringWriter sw = new StringWriter(output))
                {
                    using (HtmlTextWriter result = new HtmlTextWriter(sw))
                    {
                        _tblCache.RenderControl(result);
                    }
                }

                return output.ToString();
            }
        }
    }
}
